直線的表示。
直線仍然可以用參數方程(點和向量)來表示,並且射線和線段仍然可以看成參數有取值範圍限制的直線,並且點到直線的投影和二維情形一樣。
點到直線/線段的距離。仍然可以用面積法(注意三維叉積是向量,要用Length函數而不是fabs)。
點P到直線AB的距離:
double DistanceToLine(const Point3 &P, const Point3 &A, const Point3 &B)
{
Vector3 v1, v2;
v1 = B - A;
v2 = P - A;
return Length(Cross(v1, v2)) / Length(v1);
}
點P到線段AB的距離。
double DistanceToSegment(const Point3 &P, const Point3 &A, const Point3 &B)
{
if(A == B)
return Length(P-A);
Vector3 v1, v2, v3;
v1 = B - A;
v2 = P - A;
v3 = P - B;
if(dcmp(Dot(v1, v2)) < 0)
return Length(v2);
else if(dcmp(Dot(v1, v3)) > 0)
return Length(v3);
else
return Length(Cross(v1, v2)) / Length(v1);
}
異面直線的最短距離:
假設兩條直線分別爲l1=(p1,v1)和l2=(p2,v2),那麼最短距離會在某個q1=p1 + sv1 和 q2 = p2 + tv2 上取到,其中q1和q2分別在l1和l2上
且q1q2是這兩條異面直線的公垂線。向量q1q2=q2-q1 = p2-p1 + tv2-sv1垂直於v1, 因此Dot(p2-p1+tv2-sv1)=0.分配率:
Dot(p2-p1,v1) + t*Dot(v2,v1)-s*Dot(v1,v1)=0. 根據q1q2垂直於v2還可以得到一個一次方程,聯立。
求異面直線p1+su和p2+tv的公垂線對應的s.如果平行/重合,則返回false。
兩條直線相交的情況下算出的距離爲0,並且返回true。
bool LineDistance3D(const Point3 &P1,const Vector3 &u,const Point3 &P2,const Vector3 &v, double &s)
{
double a, b;
b = Dot(u, u)*Dot(v, v) - Dot(u, v)*Dot(u, v);
if(dcmp(b) == 0)
return false;
a = Dot(u, v)*Dot(v, P1-P2) - Dot(v, v)*Dot(u, P1-P2);
s = a / b;
return true;
}